package handler

import (
	"github.com/gin-gonic/gin"
	"github.com/lab-online/internal/lab/constant"
	"github.com/lab-online/internal/lab/domain"
	"github.com/lab-online/internal/lab/entity"
	"github.com/lab-online/internal/shared/code"
	"github.com/lab-online/pkg/auth"
	mw "github.com/lab-online/pkg/middleware"
	"github.com/lab-online/pkg/resp"
)

type Handler struct {
	domain domain.LabDomain
}

func New(domain domain.LabDomain) *Handler {
	return &Handler{domain}
}

type BaseLabReqBody struct {
	ClassID      uint `json:"classId" binding:"required,min=1"`
	ExperimentID uint `json:"experimentId" binding:"required,min=1"`
}

type LabReqBody[T any] struct {
	BaseLabReqBody
	Args T `json:"args" binding:"required"`
}

type resolverFn func(entity.LabEntity) (entity.LabEntity, error)

func commonChain[T any](resolver resolverFn) gin.HandlersChain {
	return []gin.HandlerFunc{
		validator[T](),
		commonHandler[T](resolver),
	}
}

func validator[T any]() gin.HandlerFunc {
	return mw.NewValidator(func() *mw.ValidatorOptions {
		return &mw.ValidatorOptions{
			Body: &LabReqBody[T]{},
		}
	})
}

// commonHandler 通用处理函数
func commonHandler[T any](resolver resolverFn) gin.HandlerFunc {
	return func(c *gin.Context) {
		body := c.MustGet(mw.KeyBody).(*LabReqBody[T])
		authEntity := c.MustGet(auth.KeyAuth).(auth.AuthEntity)

		labEntity := entity.New(
			entity.WithStatus(code.StatusIdle),
			entity.WithStudent(authEntity.GetUsername()),
			entity.WithArguments(body.Args),
			entity.WithClassID(body.ClassID),
			entity.WithExperimentID(body.ExperimentID),
		)

		if lab, err := resolver(labEntity); err != nil {
			resp.ErrorHandler(c, err)
		} else {
			resp.Success(c, constant.CodeExecuting, lab.GetRespBody())
		}
	}
}
